import os
import re
import yaml
from datetime import datetime, date
from flask import Blueprint, render_template, abort, redirect, url_for, current_app, request
import markdown
from fuzzywuzzy import fuzz

posts_bp = Blueprint('posts', __name__)


def parse_post(filepath):
    """解析Markdown文件并返回结构化数据"""
    try:
        with open(filepath, 'r', encoding='utf-8') as f:
            content = f.read()
    except FileNotFoundError:
        return None

    parts = content.split('---', 2)
    if len(parts) < 3:
        return None

    try:
        metadata = yaml.safe_load(parts[1].strip())
    except yaml.YAMLError:
        metadata = {}
        current_app.logger.debug("Failed to load YAML from %s", filepath)

    markdown_content = parts[2].strip()
    date_str = metadata.get('date', '1970-01-01')

    if isinstance(date_str, date):
        date_obj = date_str
    else:
        try:
            date_obj = datetime.strptime(date_str, '%Y-%m-%d').date()
        except ValueError:
            date_obj = datetime.strptime('1970-01-01', '%Y-%m-%d').date()

    modified_date = None
    if modified_str := metadata.get('modified', None):
        if isinstance(modified_str, date):
            modified_date = modified_str
        else:
            try:
                modified_date = datetime.strptime(modified_str, '%Y-%m-%d').date()
            except ValueError:
                pass

    return {
        'title': metadata.get('title', 'Untitled'),
        'date': date_obj,
        'modified_date': modified_date,
        'views': metadata.get('views', 0),
        'content': markdown_content,
        'html_content': markdown.markdown(markdown_content),
        'slug': os.path.splitext(os.path.basename(filepath))[0]
    }


def get_all_posts():
    """获取所有博文并按日期排序"""
    posts = []
    posts_dir = os.path.join(current_app.root_path, 'posts')

    for filename in os.listdir(posts_dir):
        if filename.endswith('.md'):
            post = parse_post(os.path.join(posts_dir, filename))
            if post:
                posts.append(post)

    return sorted(posts, key=lambda x: x['date'], reverse=True)


def search_posts(query):
    """根据关键词搜索博文"""
    all_posts = get_all_posts()
    results = []

    for post in all_posts:
        title_score = fuzz.partial_ratio(query.lower(), post['title'].lower())
        content_score = fuzz.partial_ratio(query.lower(), post['content'].lower())

        if title_score > 50 or content_score > 50:
            post['score'] = max(title_score, content_score)
            results.append(post)

    return sorted(results, key=lambda x: x['score'], reverse=True)


def save_post(slug, title, content):
    """保存博文到Markdown文件"""
    posts_dir = os.path.join(current_app.root_path, 'posts')
    filepath = os.path.join(posts_dir, f'{slug}.md')

    if os.path.exists(filepath):
        with open(filepath, 'r', encoding='utf-8') as f:
            existing_content = f.read()
            parts = existing_content.split('---', 2)
            if len(parts) >= 3:
                try:
                    metadata = yaml.safe_load(parts[1].strip())
                    metadata['title'] = title
                    metadata['modified'] = datetime.now().date().isoformat()
                except yaml.YAMLError:
                    metadata = {
                        'title': title,
                        'date': datetime.now().date().isoformat(),
                        'modified': datetime.now().date().isoformat()
                    }
            else:
                metadata = {
                    'title': title,
                    'date': datetime.now().date().isoformat(),
                    'modified': datetime.now().date().isoformat()
                }
    else:
        metadata = {
            'title': title,
            'date': datetime.now().date().isoformat(),
            'views': 0
        }

    with open(filepath, 'w', encoding='utf-8') as f:
        f.write(f"---\n{yaml.dump(metadata)}---\n{content}")


def delete_post(slug):
    """删除博文及所有关联图片"""
    posts_dir = os.path.join(current_app.root_path, 'posts')
    filepath = os.path.join(posts_dir, f'{slug}.md')

    if not os.path.exists(filepath):
        return

    with open(filepath, 'r', encoding='utf-8') as f:
        content = f.read()

    content_images = set(re.findall(r'\!\[.*?\]\(/static/uploads/(.*?)\)', content))
    uploads_dir = os.path.join(current_app.root_path, 'static', 'uploads')
    for img in content_images:
        img_path = os.path.join(uploads_dir, img)
        try:
            if os.path.exists(img_path):
                os.remove(img_path)
        except Exception as e:
            current_app.logger.error(f'Failed to delete image {img_path}: {str(e)}')

    os.remove(filepath)


@posts_bp.route('/')
def index():
    """首页显示博文列表"""
    all_posts = get_all_posts()
    recommended_posts = sorted(
        all_posts,
        key=lambda x: x.get('views', 0),
        reverse=True
    )[:10]
    return render_template('index.html', posts=all_posts, recommended_posts=recommended_posts)


@posts_bp.route('/post/<slug>')
def show_post(slug):
    """显示单篇博文"""
    post_path = os.path.join(current_app.root_path, 'posts', f'{slug}.md')
    post = parse_post(post_path)

    if not post:
        abort(404)

    posts_dir = os.path.join(current_app.root_path, 'posts')
    filepath = os.path.join(posts_dir, f'{slug}.md')

    with open(filepath, 'r', encoding='utf-8') as f:
        content = f.read()

    parts = content.split('---', 2)
    if len(parts) >= 3:
        try:
            metadata = yaml.safe_load(parts[1].strip())
            metadata['views'] = metadata.get('views', 0) + 1

            with open(filepath, 'w', encoding='utf-8') as f:
                f.write(f"---\n{yaml.dump(metadata)}---\n{parts[2]}")

            post['views'] = metadata['views']
        except yaml.YAMLError:
            pass

    all_posts = []
    for filename in os.listdir(posts_dir):
        if filename.endswith('.md'):
            p = parse_post(os.path.join(posts_dir, filename))
            if p:
                all_posts.append(p)

    recommended_posts = sorted(
        [p for p in all_posts if p['slug'] != post['slug']],
        key=lambda x: x.get('views', 0),
        reverse=True
    )[:10]

    return render_template('post.html', post=post, recommended_posts=recommended_posts)


@posts_bp.route('/edit/<slug>')
def edit_post(slug):
    """编辑博文"""
    post_path = os.path.join(current_app.root_path, 'posts', f'{slug}.md')
    post = parse_post(post_path)

    if not post:
        abort(404)

    return render_template('edit.html', post=post)


@posts_bp.route('/search')
def search():
    """搜索博文"""
    query = request.args.get('q', '').strip()

    if not query:
        return redirect(url_for('posts.index'))

    results = search_posts(query)
    recommended_posts = sorted(
        get_all_posts(),
        key=lambda x: x.get('views', 0),
        reverse=True
    )[:10]
    return render_template('index.html', posts=results, recommended_posts=recommended_posts, search_query=query)


@posts_bp.route('/archives')
def archives():
    """文章归档页面"""
    posts = sorted(get_all_posts(), key=lambda x: x['date'], reverse=True)
    archives = {}

    for post in posts:
        year = post['date'].year
        if year not in archives:
            archives[year] = []
        archives[year].append(post)

    return render_template('archives.html', archives=archives)


@posts_bp.route('/about')
def about():
    """关于页面"""
    return render_template('about.html')
